using System;

using Microsoft.SharePoint;
using Microsoft.SharePoint.Administration;

namespace Synergy.SharePoint.Extensions
{
	/// <summary>
	/// Extension methods for the <see cref="SPFeatureReceiverProperties"/> class.
	/// </summary>
	/// <remarks>
	///		<list type="table">
	///			<listheader><term>Version</term><description>Description</description></listheader>
	///			<item>
	///				<term>1.0</term>
	///				<description>Initial version</description>
	///			</item>
	///		</list>
	/// </remarks>
	public static class SPFeatureReceiverPropertiesExtension
	{
		/// <summary>
		/// Gets the <see cref="SPFarm"/> instance the feature was activated on.
		/// </summary>
		/// <param name="properties">The feature receiver properties.</param>
		/// <returns>The <see cref="SPFarm"/> the feature was activated on.</returns>
		/// <exception cref="InvalidOperationException">Could not retrieve an <see cref="SPFarm"/> instance.</exception>
		public static SPFarm GetFarm(this SPFeatureReceiverProperties properties)
		{
			// feature activated on a farm -- try this first, since it's likely to be the desired scope
			var farm = properties.Feature.Parent as SPFarm;
			if (farm != null)
			{
				return farm;
			}

			// feature activated on a web app
			var app = properties.Feature.Parent as SPWebApplication;
			if (app != null)
			{
				return app.Farm;
			}

			// feature activated on a site collection
			var site = properties.Feature.Parent as SPSite;
			if (site != null)
			{
				return site.WebApplication.Farm;
			}

			// feature activated on a site
			var web = properties.Feature.Parent as SPWeb;
			if (web != null)
			{
				return web.Site.WebApplication.Farm;
			}

			// unknown -- this should never happen
			throw new InvalidOperationException("Could not identify the feature scope (not farm, web app, site collection, or site).");
		}


		/// <summary>
		/// Gets the <see cref="SPWebApplication"/> instance the feature was activated on.
		/// </summary>
		/// <param name="properties">The feature receiver properties.</param>
		/// <returns>The <see cref="SPWebApplication"/> the feature was activated on.</returns>
		/// <exception cref="InvalidOperationException">Could not retrieve an <see cref="SPWebApplication"/> instance.</exception>
		public static SPWebApplication GetWebApplication(this SPFeatureReceiverProperties properties)
		{
			// feature activated on a web app -- try this first, since it's likely to be the desired scope
			var app = properties.Feature.Parent as SPWebApplication;
			if (app != null)
			{
				return app;
			}

			// feature activated on a site collection
			var site = properties.Feature.Parent as SPSite;
			if (site != null)
			{
				return site.WebApplication;
			}

			// feature activated on a site
			var web = properties.Feature.Parent as SPWeb;
			if (web != null)
			{
				return web.Site.WebApplication;
			}

			// feature activated on a farm
			var farm = properties.Feature.Parent as SPFarm;
			if (farm != null)
			{
				throw new InvalidOperationException("The feature was activated on a farm; could not retrieve a web application.");
			}

			// unknown -- this should never happen
			throw new InvalidOperationException("Could not identify the feature scope (not farm, web app, site collection, or site).");
		}

	
		/// <summary>
		/// Gets the <see cref="SPSite"/> instance the feature was activated on.
		/// </summary>
		/// <param name="properties">The feature receiver properties.</param>
		/// <returns>The <see cref="SPSite"/> the feature was activated on.</returns>
		/// <exception cref="InvalidOperationException">Could not retrieve an <see cref="SPSite"/> instance.</exception>
		public static SPSite GetSite(this SPFeatureReceiverProperties properties)
		{
			// feature activated on a site collection -- try this first, since it's likely to be the desired scope
			var site = properties.Feature.Parent as SPSite;
			if (site != null)
			{
				return site;
			}

			// feature activated on a site
			var web = properties.Feature.Parent as SPWeb;
			if (web != null)
			{
				return web.Site;
			}

			// feature activated on a web app, return first site collection -- this is not a likely scenario, since a web app feature should not retrieve a site collection (SPSite)
			var app = properties.Feature.Parent as SPWebApplication;
			if (app != null)
			{
				if (app.Sites.Count == 0)
				{
					throw new InvalidOperationException("The feature was activated on a web application with no site collections; could not retrieve a site collection.");
				}
				return app.Sites[0];
			}

			// feature activated on a farm
			var farm = properties.Feature.Parent as SPFarm;
			if (farm != null)
			{
				throw new InvalidOperationException("The feature was activated on a farm; could not retrieve a site collection.");
			}

			// unknown -- this should never happen
			throw new InvalidOperationException("Could not identify the feature scope (not farm, web app, site collection, or site).");
		}


		/// <summary>
		/// Gets the <see cref="SPWeb"/> instance the feature was activated on.
		/// </summary>
		/// <param name="properties">The feature receiver properties.</param>
		/// <returns>The <see cref="SPWeb"/> the feature was activated on.</returns>
		/// <exception cref="InvalidOperationException">Could not retrieve an <see cref="SPWeb"/> instance.</exception>
		public static SPWeb GetWeb(this SPFeatureReceiverProperties properties)
		{
			// feature activated on a site -- try this first, since it's likely to be the desired scope
			var web = properties.Feature.Parent as SPWeb;
			if (web != null)
			{
				return web;
			}

			// feature activated on a site collection
			var site = properties.Feature.Parent as SPSite;
			if (site != null)
			{
				return site.RootWeb;
			}

			// feature activated on a web app, return first site collection -- this is not a likely scenario, since a web app feature should not retrieve a site (SPWeb)
			var app = properties.Feature.Parent as SPWebApplication;
			if (app != null)
			{
				if (app.Sites.Count == 0)
				{
					throw new InvalidOperationException("The feature was activated on a web application with no site collections; could not retrieve a site.");
				}
				return app.Sites[0].RootWeb;
			}

			// feature activated on a farm
			var farm = properties.Feature.Parent as SPFarm;
			if (farm != null)
			{
				throw new InvalidOperationException("The feature was activated on a farm; could not retrieve a site.");
			}

			// unknown -- this should never happen
			throw new InvalidOperationException("Could not identify the feature scope (not farm, web app, site collection, or site).");
		}
	}
}